﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using Base;

namespace PrimerOne
{
    public class GameHandler
    {
        Matrix worldMatrix;
        Matrix viewMatrix;
        Matrix projectionMatrix;
        int points = 8;
        VertexBuffer vertexBuffer;
        VertexDeclaration vertexDeclaration;
        VertexPositionColor[] pointList;
        short[] triangleListIndices;
        IGameProxy _game;
        BasicEffect _basicEffect;
        private GraphicsDevice _graphicsDevice { get { return _game.GraphicsDevice; } }

        public GameHandler(IGameProxy gameProxy, IGraphicsDeviceManager graphicsDeviceManager)
        {
            _game = gameProxy;
            _game.LoadContentEvent += LoadContent;
            _game.InitializeEvent += Initialize;      
            _game.DrawEvent += Draw;            
        }


        private void Initialize()
        {
            InitializeEffect();
            InitializeTransform();
            InitializePointList();
            InitializeTriangleList();           
        }

        private void Draw(GameTime gameTime)
        {
            _graphicsDevice.Clear(Color.Black);

            _graphicsDevice.VertexDeclaration = vertexDeclaration;
            _basicEffect.Begin();

            foreach (EffectPass pass in _basicEffect.CurrentTechnique.Passes)
            {
                pass.Begin();
                _graphicsDevice.RenderState.FillMode = FillMode.WireFrame;
                _graphicsDevice.RenderState.CullMode = CullMode.None;
                DrawTriangleList();                
                pass.End();
            }            

            _basicEffect.End();
        }

        private void DrawTriangleList()
        {
            _graphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>(
                PrimitiveType.TriangleList,
                pointList,
                0,   // vertex buffer offset to add to each element of the index buffer
                8,   // number of vertices to draw
                triangleListIndices,
                0,   // first index element to read
                6    // number of primitives to draw
            );
        }

        private void InitializeTransform()
        {
            viewMatrix = Matrix.CreateLookAt(
                new Vector3(0.0f, 0.0f, 1.0f),
                Vector3.Zero,
                Vector3.Up
                );

            projectionMatrix = Matrix.CreateOrthographicOffCenter(
                0,
                (float)_graphicsDevice.Viewport.Width,
                (float)_graphicsDevice.Viewport.Height,
                0,
                1.0f, 1000.0f);
        }

        private void InitializeTriangleList()
        {
            int width = 4;
            int height = 2;

            triangleListIndices = new short[(width - 1) * (height - 1) * 6];

            for (int x = 0; x < width - 1; x++)
            {
                for (int y = 0; y < height - 1; y++)
                {
                    triangleListIndices[(x + y * (width - 1)) * 6] = (short)(2 * x);
                    triangleListIndices[(x + y * (width - 1)) * 6 + 1] = (short)(2 * x + 1);
                    triangleListIndices[(x + y * (width - 1)) * 6 + 2] = (short)(2 * x + 2);

                    triangleListIndices[(x + y * (width - 1)) * 6 + 3] = (short)(2 * x + 2);
                    triangleListIndices[(x + y * (width - 1)) * 6 + 4] = (short)(2 * x + 1);
                    triangleListIndices[(x + y * (width - 1)) * 6 + 5] = (short)(2 * x + 3);
                }
            }
        }

        private void InitializePointList()
        {
            vertexDeclaration = new VertexDeclaration(
                _graphicsDevice,
                VertexPositionColor.VertexElements
                );

            pointList = new VertexPositionColor[points];

            for (int x = 0; x < points / 2; x++)
            {
                for (int y = 0; y < 2; y++)
                {
                    pointList[(x * 2) + y] = new VertexPositionColor(
                        new Vector3(x * 100, y * 100, 0), Color.White);
                }
            }

            // Initialize the vertex buffer, allocating memory for each vertex.
            vertexBuffer = new VertexBuffer(_graphicsDevice,
                VertexPositionColor.SizeInBytes * (pointList.Length),
                BufferUsage.None);

            // Set the vertex buffer data to the array of vertices.
            vertexBuffer.SetData<VertexPositionColor>(pointList);
        }

        private void LoadContent()
        {
            InitializeEffect();
            InitializeTransform();
            InitializePointList();
            InitializeTriangleList();
        }

        private void InitializeEffect()
        {
            vertexDeclaration = new VertexDeclaration(
                _graphicsDevice,
                VertexPositionColor.VertexElements
                );

            _basicEffect = new BasicEffect(_graphicsDevice, null);
            _basicEffect.VertexColorEnabled = true;

            worldMatrix = Matrix.CreateTranslation(_graphicsDevice.Viewport.Width / 2f - 150,
                _graphicsDevice.Viewport.Height / 2f - 50, 0);

            _basicEffect.World = worldMatrix;
            _basicEffect.View = viewMatrix;
            _basicEffect.Projection = projectionMatrix;
        }

        public void Start()
        {
            using (_game)
            {
                _game.Run();
            }
        }
    }
}
